package com.yu.waterstation.system.modules.system.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yu.waterstation.common.common.config.property.IOProperty;
import com.yu.waterstation.common.common.exception.ServiceException;
import com.yu.waterstation.common.common.util.GeneratorUtil;
import com.yu.waterstation.common.common.util.browser.UserAgentUtils;
import com.yu.waterstation.common.common.util.ip.IpUtil;
import com.yu.waterstation.common.service.RedisService;
import com.yu.waterstation.system.common.util.session.SessionUtil;
import com.yu.waterstation.system.modules.system.mapper.LoginLogMapper;
import com.yu.waterstation.system.modules.system.mapper.RoleMapper;
import com.yu.waterstation.system.modules.system.mapper.RolePermissionMapper;
import com.yu.waterstation.system.modules.system.mapper.SysUserMapper;
import com.yu.waterstation.common.entity.system.LoginLog;
import com.yu.waterstation.common.entity.system.SysUser;
import com.yu.waterstation.common.entity.system.dto.SysUserDTO;
import com.yu.waterstation.common.entity.system.form.SysUserLoginVO;
import com.yu.waterstation.common.entity.system.form.UpdatePasswordVo;
import cz.mallat.uasparser.UserAgentInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Date;

@Slf4j
@Service
public class SysUserService  {

    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private RolePermissionMapper rolePermissionMapper;
    @Resource
    private IOProperty ioProperty;
    @Resource
    private LoginLogMapper loginLogMapper;

    @Transactional(rollbackFor = Exception.class)
    public SysUserDTO login(SysUserLoginVO loginVo, HttpServletRequest request) throws Exception {
//        // 校对验证码
//        String verifyCode = String.valueOf(redisService.get(Const.CONST_verify_code_redis_prefix + loginVo.getUuid()));
//        redisService.del(Const.CONST_verify_code_redis_prefix, loginVo.getUuid());
//        if (StringUtils.isEmpty(verifyCode) || !verifyCode.equals(loginVo.getVerifyCode())) {
//            addLoginLog(loginVo, request, false);
//            throw ServiceException.CONST_verify_code_error_or_expire;
//        }

        SysUser user = sysUserMapper.selectOne(new QueryWrapper<SysUser>()
                .eq("username", loginVo.getUsername())
                .eq("password", GeneratorUtil.md5Base64(loginVo.getPassword())));
        if (user == null) {
            log.error("[管理员登录失败] {}", loginVo);
            addLoginLog(loginVo, request, false);
            throw ServiceException.CONST_login_failed;
        }

        if (!user.getStatus()) {
            log.error("[管理员登录失败 账号冻结] {}", loginVo);
            addLoginLog(loginVo, request, false);
            throw ServiceException.CONST_user_is_forbidden;
        }

        SysUserDTO userDTO = new SysUserDTO();
        BeanUtils.copyProperties(user, userDTO, "password");
        userDTO.setRoleName(roleMapper.getRoleNameByRoleid(user.getRoleId()));
        // 获取权限
        userDTO.setPermissions(rolePermissionMapper.selectPerimssionByRoleId(user.getRoleId()));
        SessionUtil.setSysUserSession(userDTO);
        log.info("[管理员登录] {}", userDTO);
        addLoginLog(loginVo, request, true);
        return userDTO;
    }

    @Async
    public void addLoginLog(SysUserLoginVO loginForm, HttpServletRequest request, boolean isSuccess) {
        LoginLog loginLog = new LoginLog();

        loginLog.setUsername(loginForm.getUsername()); // 用户名
        loginLog.setIp(IpUtil.getIp(request)); // ip地址

        UserAgentInfo userAgentInfo = UserAgentUtils.parse(request.getHeader("User-Agent"));
        if (userAgentInfo != null) {
            loginLog.setOsName(userAgentInfo.getOsName()); // 操作系统名称 eg: Windows
            loginLog.setBrowserName(userAgentInfo.getUaFamily()); // 游览器名称 eg: Chrome
        }

        loginLog.setSuccess(isSuccess); // 成功与否
        loginLog.setTimestamp(new Date());
        loginLogMapper.insert(loginLog);
    }

    @Transactional(rollbackFor = Exception.class)
    public int updatePassword(Integer userId, UpdatePasswordVo params) throws ServiceException {
        if (StringUtils.isEmpty(params.getOldPassword()) || StringUtils.isEmpty(params.getNewPassword())
                || params.getNewPassword().length() < 6 || params.getNewPassword().length() > 18)
            throw ServiceException.CONST_password_pattern_error;
        if (params.getOldPassword().equals(params.getNewPassword()))
            throw ServiceException.CONST_new_password_can_not_equals_old_password;

        SysUser user = sysUserMapper.selectById(userId);
        if (!GeneratorUtil.md5Base64(params.getOldPassword()).equals(user.getPassword()))
            throw ServiceException.CONST_old_password_error;

        user.setPassword(GeneratorUtil.md5Base64(params.getNewPassword()));
        return sysUserMapper.updateById(user);
    }

    // 更新头像
    @Transactional(rollbackFor = Exception.class)
    public int updateUserAvatar(MultipartFile file, SysUserDTO currentSysUser) throws ServiceException {
        try {
            File dir = new File(ioProperty.getImageFileRootPath());
            if (!dir.exists()) // 不存在该目录就创建
                dir.mkdir();
            String userAvatar = "userAvatar-" + currentSysUser.getId() + ".jpg" ;;
            file.transferTo(new File(dir, userAvatar));
            if (file.getSize() > 1024 * 1024)
                throw ServiceException.CONST_image_size_over_1MB; // 文件超过1MB

            SysUser user = new SysUser();
            user.setId(currentSysUser.getId());
            user.setAvatar(userAvatar);
            int count = sysUserMapper.updateById(user);
            currentSysUser.setAvatar(userAvatar);
            SessionUtil.updateSysUserSession(currentSysUser); // 更新缓存里的会话信息
            return count;
        } catch (Exception e) {
            throw ServiceException.CONST_image_upload_failed;
        }
    }
}
